//使用express模块快速搭建web服务器
var express = require('express');
var app = express();
var http = require('http').Server(app);
//使用socket.io监听事件
var io = require('socket.io')(http);
//使用express发送css js等静态资源
app.use(express.static('public'));

//express获得GET请求时将index.html文件返回给浏览器
app.get('/', function (req, res) {
    res.sendFile(__dirname + '/index.html');
});

var userServer = {}, // 缓存每一个用户的websocket实例
    userLists = {}, // 在线列表
    userCounts = 0; // 在线人数


/**
 * socket监听连接事件
 */
io.on('connection', function (socket) {
    console.log('一个用户连接成功');
    //socket监听失去连接的事件
    socket.on('disconnect', function () {
        // 判断当前退出用户是否在在线列表里面
        if (userLists.hasOwnProperty(socket.userId)) {
            var user = { userId: socket.userId, userName: userLists[socket.userId] };

            // 删除在线列表和服务列表中退出用户信息
            delete userLists[socket.userId];
            delete userServer[socket.userId];
            userCounts--;

            /**
             * 向所有用户广播用户退出
             * @param userLists 新的在线列表
             * @param userCounts 新的在线人数
             * @param user 退出的用户信息
             */
            io.emit('loginout', { userLists: userLists, userCounts: userCounts, user: user });
            console.log('用户' + user.userName + '退出了房间');
        }
    });

    /**
     * socket监听登录时间
     * @param user 登录的用户信息
     */
    socket.on('login', function (user) {
        socket.userId = user.userId;

        // 进行点对点广播， 缓存socket实例
        userServer[user.userId] = socket;

        // 判断登录的用户不在在线列表中
        if (!userLists.hasOwnProperty(user.userId)) {
            userLists[user.userId] = user.userName;
            userCounts++;
        }

        /**
         * 向所有用户广播有用户登录
         * @param userLists 新的在线列表
         * @param userCounts 新的在线人数
         * @param user 登录的用户信息
         */
        io.emit('login', { userLists: userLists, userCounts: userCounts, user: user });
        console.log('用户' + user.userName + '进入了房间');
    });

    /**
     * 当socket监听到了'chat message'事件
     * @param msg 消息发送的内容加用户信息
     */
    socket.on('message', function (msg) {
        // 当有privateId信息时表示为私聊信息，推送给特定用户端
        if (msg.privateId) {
            if (userServer[msg.privateId]) {
                /**
                 * 将收到的信息返回给目标用户及自己的客户端
                 * @param msg 消息内容
                 * @param user 信息发送人id
                 * @param userLists 在线人员列表
                 * @param privateId 接收消息人id
                 * @param orgin 用于用户端判断消息是自己发的还是对方发的
                 * @param img 是否为图片信息
                 */
                userServer[msg.privateId].emit('message', { msg: msg.msg, user: msg.userId, userLists: userLists, privateId: msg.privateId, orgin: 'receiver', img: msg.img });
                userServer[msg.userId].emit('message', { msg: msg.msg, user: msg.userId, userLists: userLists, privateId: msg.privateId, orgin: 'sender', img: msg.img });
            } else {
                // 当userServer中没有对方socket实例提示自己对方已下线
                userServer[msg.userId].emit('pri_error', { msg: msg.msg, user: msg.userId, userLists: userLists, privateId: msg.privateId, orgin: 'sender' });
            }
        } else {
            /**
             * 群聊时，将收到的信息返回给所有客户端
             * @param msg 消息内容
             * @param user 消息发送人id
             * @param userLists 在线人员列表
             */
            io.emit('message', { msg: msg.msg, user: msg.userId, userLists: userLists, img: msg.img });
        }
    });
});

//服务器监听端口3000
http.listen(3000, function () {
    console.log('listening on *:3000');
})